import axios from 'axios'
import qs from 'qs'
const { $lodash, ElMessage } = window

// 配置 请求默认基础地址
const { VUE_APP_BASE_API } = (import.meta as any).env

// 遍历 modules文件导入到index.js
const modulesFiles = (import.meta as any).globEager('./**/*.ts')
const modules = {}
Object.keys(modulesFiles).forEach((fileName) => {
  const name = fileName.replace(/\.\/|\.ts/g, '')
  const nameList = name.split('/')

  modulesSet({
    modules,
    module: modulesFiles[fileName].default,
    nameList: nameList,
  })
})
function modulesSet({
  modules,
  module,
  modulesPrev,
  nameList,
  i = 0,
}: {
  modules: any
  module: any
  nameList: any
  modulesPrev?: any
  i?: any
}) {
  let name = nameList[i]
  if (nameList.length == i + 1) {
    if (name == 'index') {
      modulesPrev[nameList[i - 1]] = Object.assign(
        module,
        modulesPrev[nameList[i - 1]],
      )
      return
    }

    modules[name] = module
    return
  }

  modules[name] = modules[name] || {}
  modulesSet({
    modules: modules[name],
    modulesPrev: modules,
    nameList,
    module,
    i: ++i,
  })
}

// 根据key获取对应的Url信息,key以英文输入法的.分隔开
const changeUrl = (key: any) => {
  if (!key) return undefined
  let segments = key.indexOf('/') < 0 ? key.split('.') : key.split('/')
  let result: any = modules
  segments.forEach((segment: any) => {
    result = result[segment]
  })
  return result
}

let loadingAll: any = {} // 对象 加载中

// create an axios instance
const service = axios.create({
  // baseURL: '', // api 的 base_url
  // validateStatus: function(status) { // 获取状态码
  //   // return status >= 200 && status < 300; // 默认
  // },
  withCredentials: true, // 跨域请求时发送 cookies
  timeout: 1 * 60 * 1000, // 超时时间
  headers: { 'Content-Type': 'application/json' },
  //   paramsSerializer: function (params) {
  //     let result = ''
  //     Object.keys(params).forEach(
  //       (key, index) => (result += `${index ? '&' : ''}${key}=${params[key]}`)
  //     )
  //     return result
  //   }, // 参数修改 get请求
})

// request interceptor
service.interceptors.request.use(
  (config) => {
    // console.log('请求参数', config)
    let {
      headers,
      contentType,
      IsRealUrl = false,
      IsDeleteParam,
      url,
    }: {
      headers?: any
      contentType?: any
      IsRealUrl?: any
      IsDeleteParam?: any
      url?: any
    } = config

    let { $util } = window
    const accessToken = $util.storage.local({ key: 'ACCESS_TOKEN' })

    // 设置 请求头
    if (accessToken && url.indexOf('auth/oauth/token') < 0) {
      config.headers.Authorization = 'bearer ' + accessToken
    } else if (!config.headers.Authorization) {
      config.headers.Authorization = 'Basic ZmViczoxMjM0NTY='
    }

    // 判断 是否修改URL地址
    if (!IsRealUrl) {
      let urlInfo = changeUrl(config.url)
      if (!urlInfo) {
        Promise.reject(`url地址未找到匹配记录: ${config.url}`)
        return
      }
      const { url, urlLocal, method = 'get' } = urlInfo

      // 判断 是否请求本地JSON
      config.method = method

      if (url) {
        // 接口 正常
        if (url.slice(0, 4) == 'http') return (config.url = url)
        config.url = `${VUE_APP_BASE_API}${url[0] == '/' ? url : '/' + url}`
      } else {
        // 接口 本地
        config.url = urlLocal
        config.method = 'get'
      }
    }

    // 判断 是否post请求 参数赋值
    if (config.method === 'post') {
      // headers['Content-Type'] =
      //   contentType || 'application/x-www-form-urlencoded'

      // 处理动态拼接URL(带path参数的api：system/{params})
      //   if (config.servUri) config.url += '/' + config.servUri

      if (!config.data) config.data = qs.stringify(config.params)

      if (IsDeleteParam) delete config.params
    }

    // 判断 是否为文件
    // if (config.headers['Content-Type'] && config.headers['Content-Type'].indexOf('multipart') > -1) return config
    // 清缓存 get请求 添加时间戳
    if (config.method === 'get') {
      config.params = config.params || {}
      if (!config.params.t) {
        config.params.t = Date.parse(new Date().toString()) / 1000
      } else {
        config.params._t = Date.parse(new Date().toString()) / 1000
      }
    }

    // 判断 是否加载中
    if (loadingAll[config.url || 'ts']) {
      loadingAll[config.url || 'ts'].loading = true
    }

    return config
  },
  (error) => {
    console.log('error 请求', error) // for debug
    return Promise.reject(error)
  },
)

// response interceptor
service.interceptors.response.use(
  /**
   * 下面的注释为通过在response里，自定义code来标示请求状态
   * 当code为200正常，否则该请求有误
   */
  async (response) => {
    // console.log('返回', response)

    const { config, data } = response

    // 判断 是否loading加载中
    if (loadingAll[config.url || 'ts']) {
      loadingAll[config.url || 'ts'].loading = false
    }

    //  请求正常
    // if (data.code == 200 || data.success == 200 || data.success == true || data.errcode == 0) return data

    // 异常请求
    let res = await resError({ code: data.code, data, config })
    if (res) return res

    return data
  },
  async (error) => {
    console.log('error 返回', error) // for debug

    const { status, data, config } = error.response

    // 判断 是否loading加载中
    if (loadingAll[config.url]) loadingAll[config.url].loading = false

    let res = await resError({ code: status, data, config })
    if (res) return res

    return Promise.reject('error')
  },
)

// 返回错误处理
async function resError({
  code,
  data,
  config,
}: {
  code: any
  data: any
  config: any
}) {
  if (!code) return

  let { $api, $router, $store } = window
  const { account } = $store
  let message = data?.message || '系统内部异常，请联系网站管理员！'
  let res = null
  config.IsRealUrl = true

  switch (code) {
    case 400:
      ElMessage.error(message)
      break

    case 401:
      res = await $api.login.refresh({
        grant_type: 'refresh_token',
        refresh_token: account.refreshToken,
      })
      if (res) {
        account.login(res)
        return service.request(config)
      }
      break

    case 403:
      // 登录过期
      if (message.indexOf('Invalid refresh token') > -1) {
        if (process.env.VUE_APP_ENV !== 'development') {
          window.$util.iframe.postMessage({
            message: { code: 401 },
          })
          return
        }

        $router.push('/login')
        ElMessage.error('登录已过期，请重新登录！')
        return
      }

      ElMessage.error(message)
      break

    case 404:
      ElMessage.error('很抱歉，资源未找到！')
      break

    case 500:
      ElMessage.error(message)
      break

    default:
      if (message === 'refresh token无效') {
        $router.push('/login')
        ElMessage.error('登录已过期，请重新登录！')
      }
      break
  }
}

export default service

// 设置 api
let api = $lodash.cloneDeep(modules)
let setApi = ({ data }: { data: any }) => {
  Object.keys(data).forEach((key) => {
    let { url, urlLocal, method, headers, IsDeleteParam } = data[key]
    if (!url && !urlLocal) return setApi({ data: data[key] })

    if (url) {
      // 接口 正常
      if (url.slice(0, 4) == 'http') return
      url = `${VUE_APP_BASE_API}${url[0] == '/' ? url : '/' + url}`
    } else {
      // 接口 本地
      url = urlLocal
      method = 'get'
    }

    data[key] = function (params: any, loading: any) {
      loadingAll[url] = loading

      // @ts-ignore
      return service({
        url,
        method,
        headers,
        params,
        data: params,
        loading,
        IsRealUrl: true,
        IsDeleteParam,
      })
    }
  })
}
setApi({ data: api })

export { api }
